// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: qjs_event_listener_impl.cpp
// Description: EventListenerImpl Class
//      Author: Ziming Li
//     Created: 2022-03-31
// -------------------------------------------------
// Copyright (C) 2022 MingYang Software Technology.
// -------------------------------------------------

#include "./qjs_event_listener_impl.h"

#include "blinkit/blink/renderer/bindings/core/qjs/qjs.h"
#include "blinkit/blink/renderer/bindings/core/qjs/qjs_recursion_scope.h"
#include "blinkit/blink/renderer/bindings/core/script_controller.h"
#include "blinkit/blink/renderer/core/dom/ExecutionContext.h"

namespace BlinKit {
namespace qjs {

EventListenerImpl::EventListenerImpl(JSContext *ctx, JSValue listener)
    : EventListener(JSEventListenerType), m_ctx(ctx), m_listener(JS_DupValue(ctx, listener))
{
    ScriptController::From(m_ctx)->RegisterEventListener(m_listener, this);
}

EventListenerImpl::~EventListenerImpl(void)
{
    ScriptController::From(m_ctx)->UnregisterEventListener(m_listener);
    JS_FreeValue(m_ctx, m_listener);
}

void EventListenerImpl::handleEvent(ExecutionContext *executionContext, Event *event)
{
    ASSERT(executionContext->isDocument());

    RecursionScope _(m_ctx);

    JSValue arg = ScriptController::From(m_ctx)->WrapEvent(event);
    JSValue ret = JS_Call(m_ctx, m_listener, JS_UNDEFINED, 1, &arg);
    if (JS_IsException(ret))
    {
        DumpException(m_ctx);
        ASSERT(!JS_IsException(ret));
    }
    JS_FreeValue(m_ctx, ret);
    JS_FreeValue(m_ctx, arg);
}

GCRefPtr<EventListener> EventListenerImpl::Wrap(JSContext *ctx, JSValue listener, bool createIfNotExists)
{
    EventListener *ret = ScriptController::From(ctx)->FindEventListener(listener);
    if (nullptr == ret && createIfNotExists)
        ret = new EventListenerImpl(ctx, listener);
    return GCWrapShared(ret);
}

} // namespace qjs
} // namespace BlinKit
